package com.amap.demo;

import org.apache.commons.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * @author liuyi
 * @since 2025/10/31 11:09
 */

public class CheckSignUtils {


    public static boolean checkSign(Map<String, String> paramFromAmap) throws Exception {
        String amapPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAle9Evy4y/5EDQfz5hxJL00B+OMnFEl/HUqEqLpkh0da/keZBNuxpoX6MJiF3cSTj8AukoMCcj8ycSX4iqprahveT68Y2+j/D/3XCeJxbeISBDb9+8qT+ff/Y8xtLxXRJGkmNZPDodLlqcI5rtR78yT9a985gzKPOWesauPesxdgRwcxyPZqDfAuqVoRGFMgJhVIg/fMYDq3hXT75yO4tE6DTlvdZmb8iHoxZ6hXms6tOfQEdiiXpjhautnHJcAsdw55kSvms1zOsdv68tw3Y2ogqm8Wg0ukI6tBxaBtI65gyxwM4GLW5b4Z6DbGg9KJUdAGPcqPs+QzvUl0mqXm2CQIDAQAB";
        String signContent = getSignContent(paramFromAmap);
        return doCheckSign(signContent, (String)paramFromAmap.get("sign"), amapPublicKey);
    }

    private static String getSignContent(Map<String, String> paramMap) throws UnsupportedEncodingException {
        StringBuilder content = new StringBuilder();
        List<String> keys = new ArrayList(paramMap.keySet());
        Collections.sort(keys);
        for(int i = 0; i < keys.size(); ++i) {
            String key = (String)keys.get(i);
            if (!"sign_type".equals(key) && !"sign".equals(key) && !"need_encrypt".equals(key)) {
                String value = (String)paramMap.get(key);
                if (key != null && !key.isEmpty() && value != null && !value.isEmpty()) {
                    String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
                    if (i > 0) {
                        content.append("&");
                    }

                    content.append(key).append("=").append(encodedValue);
                }
            }
        }
        return content.toString();
    }

    private static boolean doCheckSign(String content, String sign, String amapPublicKey) throws GeneralSecurityException {
        byte[] publicKeyBytes = Base64.decodeBase64(amapPublicKey.getBytes(StandardCharsets.UTF_8));
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("SHA256WithRSA");
        signature.initVerify(publicKey);
        signature.update(content.getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = Base64.decodeBase64(sign.getBytes(StandardCharsets.UTF_8));
        return signature.verify(signBytes);
    }
}
